package app

import (
	"log"
	"time"

	"github.com/wailsapp/wails/v2/pkg/runtime"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

type Book struct {
	ID        uint `gorm:"primarykey"`
	Name      string
	LastLine  int
	Total     int
	CreatedAt time.Time
	UpdatedAt time.Time
}

type BooksList struct {
	Data  []Book
	Total int
}

type BookFast struct {
	Book         Book
	Dirs         []Dir
	FullLen      int
	Content      []string
	ContentStart int
}

type BookAfterProc struct {
	Book Book
	Full []string
}

var db *gorm.DB

func init() {
	var err error
	db, err = gorm.Open(sqlite.Open("dat.db"), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}
	db.AutoMigrate(&Book{})
}

func (a *app) GetBooks(name string, page int, pagesize int) (BooksList, error) {
	var books []Book
	if page < 1 {
		page = 1
	}
	if pagesize < 1 {
		pagesize = 10
	}
	result := db.Where("name LIKE ?", "%"+name+"%").Limit(pagesize).Offset((page - 1) * pagesize).Find(&books)
	if result.Error != nil {
		return BooksList{}, result.Error
	}
	var total int64
	result = db.Model(&Book{}).Where("name LIKE ?", "%"+name+"%").Count(&total)
	if result.Error != nil {
		return BooksList{}, result.Error
	}
	return BooksList{Data: books, Total: int(total)}, nil
}

func (a *app) CreateBook() ([]string, error) {
	filter := runtime.FileFilter{
		Pattern: "*.txt",
	}
	txts, err := runtime.OpenMultipleFilesDialog(a.Ctx, runtime.OpenDialogOptions{
		Title:   "Select txt files",
		Filters: []runtime.FileFilter{filter},
	})
	if err != nil {
		return nil, err
	}

	var names = make([]string, 0)
	for _, txt := range txts {
		name, cnt, err := copyTxt(txt)
		if err != nil {
			return nil, err
		}
		log.Println(name, cnt)
		result := db.Create(&Book{Name: name, Total: cnt})
		if result.Error != nil {
			return nil, result.Error
		}
		names = append(names, name)
	}

	return names, nil
}

func (a *app) DeleteBook(id uint) error {
	result := db.Delete(&Book{}, id)
	if result.Error != nil {
		return result.Error
	}
	return nil
}

func (a *app) GetBook(id uint) (BookFast, error) {
	var book Book
	result := db.First(&book, id)
	if result.Error != nil {
		return BookFast{}, result.Error
	}
	// 打印消耗时间
	tstart := time.Now()
	fastBook, err := procBook(book)
	if err != nil {
		return BookFast{}, err
	}
	log.Println("procBook:", time.Since(tstart))
	return fastBook, nil
}

func (a *app) UpdateBookHistory(id uint, lastLine int) error {
	result := db.Model(&Book{}).Where("id = ?", id).Update("last_line", lastLine)
	if result.Error != nil {
		return result.Error
	}
	return nil
}

func (a *app) ExportBookAfterProc() BookAfterProc {
	return BookAfterProc{}
}
